# -*- coding: utf-8 -*-
"""
@Time    : 2024/9/12 19:11 
@Author  : ZhangShenao 
@File    : 2.访问可见性问题.py 
@Desc    : 访问可见性问题

在Python中,属性和方法的访问权限只有两种:private和public
如果希望属性是private的,在给属性命名时可以用两个下划线(__)作为开头

但是,实际上Python并没有在语法层面严格保证属性和方法的私有性
而是将私有的属性和方法,换了另外一个名字,来避免外部访问
事实上,如果了解重命名的规则,在外边依然可以访问私有的属性和方法
访问规则为:对象名._类名__方法/属性

在实际开发中,并不建议将属性设置为私有的
因为这会导致子类无法访问
所以大多数Python程序员会遵循一种命名惯例
即让属性名以单下划线开头来表示属性是受保护的
本类之外的代码在访问这样的属性时应该要保持慎重
这种做法并不是语法上的规则
单下划线开头的属性和方法外界仍然是可以访问的
所以更多的时候它是一种暗示或隐喻
"""


class VisibilityTest:
    """访问可见性测试"""

    def __init__(self, foo: int):
        """
        构造函数
        :param foo:
        """

        # 以双下划线__开头的属性是private的,外部无法访问
        self.__foo = foo

    def __bar(self):
        """
        私有方法
        双下划线__开头的方法是private的,外部无法调用
        """

        print("调用__bar方法")


if __name__ == '__main__':
    # 创建对象
    vt = VisibilityTest(foo=123)

    # 外部无法访问私有属性
    # AttributeError: 'VisibilityTest' object has no attribute '__foo'
    # print(f"vt.__foo: {vt.__foo}")

    # 外部无法调用私有方法
    # AttributeError: 'VisibilityTest' object has no attribute '__bar'
    # vt.__bar()

    # 实际上Python并没有在语法层面严格保证属性和方法的私有性
    # 而是将私有的属性和方法,换了另外一个名字,来避免外部访问
    # 事实上,如果了解重命名的规则,在外边依然可以访问私有的属性和方法
    # 访问规则为:对象名._类名__方法/属性
    print(f"vt._VisibilityTest__foo: {vt._VisibilityTest__foo}")
    vt._VisibilityTest__bar()
